# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: jaewon

import datetime
import json
import logging

from absl import app, flags

from coin.base.datetime_util import to_datetime
from coin.base.param_util import to_list
from coin.strategy.mm.simple_sim.runner_util import (get_profile_module,
                                                     get_num_strategies,
                                                     run_sim_strategy)


def parse_datetime(dt_str):
  if len(dt_str) == len('YYYYMMDD-HHMMSS'):
    return datetime.datetime.strptime(dt_str, '%Y%m%d-%H%M%S')
  elif len(dt_str) == len('YYYYMMDD-HHMM'):
    return datetime.datetime.strptime(dt_str, '%Y%m%d-%H%M')
  elif len(dt_str) == len('YYYYMMDD-HH'):
    return datetime.datetime.strptime(dt_str, '%Y%m%d-%H')
  elif len(dt_str) == len('YYYYMMDD'):
    return datetime.datetime.strptime(dt_str, '%Y%m%d')
  else:
    raise ValueError('Unknown datetime format: %s' % dt_str)


def main(argv):
  FLAGS = flags.FLAGS

  assert FLAGS.profile is not None
  assert FLAGS.timerange_from_ts is not None
  assert FLAGS.timerange_to_ts is not None

  try:
    profile_args = argv[1:]
    profile = get_profile_module(FLAGS.profile, profile_args)
  except ModuleNotFoundError:
    return 2

  from_ts = parse_datetime(FLAGS.timerange_from_ts)
  to_ts = parse_datetime(FLAGS.timerange_to_ts)

  num_strat = get_num_strategies(profile, from_ts, to_ts)
  max_idx = num_strat - 1
  from_idx = FLAGS.strategy_from_idx or 0
  to_idx = min(FLAGS.strategy_to_idx or max_idx, max_idx)

  logging.info('Initiating %s - %s: %d - %d',
               to_datetime(from_ts),
               to_datetime(to_ts),
               from_idx,
               to_idx)
  result = run_sim_strategy(FLAGS.profile,
                            from_ts,
                            to_ts,
                            from_idx,
                            to_idx,
                            root_dir=FLAGS.flow_root_dir,
                            profile_args=profile_args)
  out_str = json.dumps(result, sort_keys=True, indent=2)

  if FLAGS.out is None:
    print(out_str)
  else:
    with open(FLAGS.out, 'w') as f:
      f.write(out_str)

  if FLAGS.show_aggregated_result:
    profile.aggregate_result(result)


if __name__ == '__main__':
  logging.basicConfig(
      level='DEBUG',
      format='%(levelname)8s %(asctime)s %(name)s %(filename)s:%(lineno)d] %(message)s')
  logging.getLogger('coin.exchange.util.feed_checker').setLevel(logging.WARNING)

  flags.DEFINE_string('profile', None, 'Profile name')
  flags.DEFINE_string('timerange_from_ts', None, 'Start timestamp in YYYYMMDD-HHMMSS format.')
  flags.DEFINE_string('timerange_to_ts', None, 'End timestamp in YYYYMMDD-HHMMSS format.')
  flags.DEFINE_integer('strategy_from_idx',
                       None,
                       'If specified, runs only strategies in [from_idx, to_idx], inclusive.')
  flags.DEFINE_integer('strategy_to_idx',
                       None,
                       'If specified, runs only strategies in [from_idx, to_idx], inclusive.')
  flags.DEFINE_string('out', None, 'If specified, writes the result to the specified file.')
  flags.DEFINE_bool('show_aggregated_result', False, 'If true, shows aggregated result to stdout.')
  flags.DEFINE_string('flow_root_dir',
                      None,
                      'If specified, use the specified directory as flow roor directory.')
  app.run(main)
